# -*- coding: mbcs -*-
from part import *
from material import *
from section import *
from assembly import *
from step import *
from interaction import *
from load import *
from mesh import *
from optimization import *
from job import *
from sketch import *
from visualization import *
from connectorBehavior import *

A = 10.0     # 矩形长度
B = 10.0     # 矩形宽度

X_N = 5      # x轴阵列个数
Y_N = 5      # y轴阵列个数
 
X_SPACE = A  # x轴阵列间距
Y_SPACE = B  # y轴阵列间距

YOUNGS_MODULUS = 210000.0  # 杨氏模量
POISSONS_RATIO = 0.3       # 泊松比
THICKNESS = 1.0            # 矩形厚度

# 生成矩形胞元顶点
def generateCellUnit():

  point_1 = (0, 0)
  point_2 = (0, B)
  point_3 = (A, B)
  point_4 = (A, 0)

  points = [point_1, point_2, point_3, point_4]

  return points

# 移动点
def move(offset_x, offset_y, points):

  res = []

  for point in points:
    movedPoint = (point[0] + offset_x, point[1] + offset_y)
    res.append(movedPoint)

  return res

# 创建part
def createPart(points, partName):

  mdb.models['Model-1'].ConstrainedSketch(name='__profile__', sheetSize=200.0)
  mdb.models['Model-1'].sketches['__profile__'].Line(point1=points[0], point2=points[1])
  mdb.models['Model-1'].sketches['__profile__'].Line(point1=points[1], point2=points[2])
  mdb.models['Model-1'].sketches['__profile__'].Line(point1=points[2], point2=points[3])
  mdb.models['Model-1'].sketches['__profile__'].Line(point1=points[3], point2=points[0])

  mdb.models['Model-1'].Part(dimensionality=THREE_D, name=partName, type=
      DEFORMABLE_BODY)
  mdb.models['Model-1'].parts[partName].BaseShell(sketch=
      mdb.models['Model-1'].sketches['__profile__'])
  del mdb.models['Model-1'].sketches['__profile__']

# 阵列part
def arrayPart():

  cellUnitPoints = generateCellUnit()
  for i in range(Y_N):
    for j in range(X_N):
      partName = "Part-" + str(i+1) + '-' + str(j+1)
      points = move(X_SPACE * j, Y_SPACE * i, cellUnitPoints)
      createPart(points, partName)

# 装配part
def assembly():
  mdb.models['Model-1'].rootAssembly.DatumCsysByDefault(CARTESIAN)
  for i in range(Y_N):
    for j in range(X_N):
      partName = "Part-" + str(i+1) + '-' + str(j+1)
      mdb.models['Model-1'].rootAssembly.Instance(dependent=ON, name=partName + '-1', 
        part=mdb.models['Model-1'].parts[partName])

mdb.models['Model-1'].ConnectorSection(assembledType=HINGE, name='ConnSect-Hinge')

# 添加转动副
def addHinge(partName_1, num_1, partName_2, num_2, count):

  mdb.models['Model-1'].rootAssembly.DatumCsysByThreePoints(coordSysType=
    CARTESIAN, line1=(1.0, 0.0, 0.0), line2=(0.0, 1.0, 0.0), origin=
    mdb.models['Model-1'].rootAssembly.instances['Part-1-1-1'].vertices[1])
  mdb.models['Model-1'].rootAssembly.WirePolyLine(mergeType=IMPRINT, meshable=
      False, points=((
      mdb.models['Model-1'].rootAssembly.instances[partName_1].vertices[num_1], 
      mdb.models['Model-1'].rootAssembly.instances[partName_2].vertices[num_2]), ))
  mdb.models['Model-1'].rootAssembly.features.changeKey(fromName='Wire-' + str(count+1), 
      toName='Wire-' + str(count+1))
  mdb.models['Model-1'].rootAssembly.Set(edges=
      mdb.models['Model-1'].rootAssembly.edges.getSequenceFromMask(('[#1 ]', ), )
      , name='Wire-' + str(count+1) + '-Set-1')
  mdb.models['Model-1'].rootAssembly.SectionAssignment(region=
      mdb.models['Model-1'].rootAssembly.sets['Wire-' + str(count+1) + '-Set-1'], sectionName=
      'ConnSect-Hinge')
  mdb.models['Model-1'].rootAssembly.sectionAssignments[count].getSet()
  keys = mdb.models['Model-1'].rootAssembly.datums.keys()
  mdb.models['Model-1'].rootAssembly.ConnectorOrientation(localCsys1=
      mdb.models['Model-1'].rootAssembly.datums[keys[-1]], region=
      mdb.models['Model-1'].rootAssembly.allSets['Wire-' + str(count+1) + '-Set-1'])

def arrayHinge():

  # 转动副添加计数
  count = 0

  # 第y行矩形之间的转动副
  for y in range(Y_N):

    # 奇数行
    if(y % 2 == 0):
      
      # 奇数行下方的转动副
      for i in range(X_N // 2):
        partName_1 = 'Part-' + str(y+1) + '-' + str(2*i+1) + '-1'
        partName_2 = 'Part-' + str(y+1) + '-' + str(2*i+2) + '-1'
        addHinge(partName_1, 1, partName_2, 0, count)
        count += 1
      
      # 奇数行，偶数列时，上方的转动副
      if(X_N % 2 == 0):
        for m in range(X_N // 2 - 1):
          partName_1 = 'Part-' + str(y+1) + '-' + str(2*m+2) + '-1'
          partName_2 = 'Part-' + str(y+1) + '-' + str(2*m+3) + '-1'
          addHinge(partName_1, 2, partName_2, 3, count)
          count += 1
      
      # 奇数行，奇数列时，上方的转动副
      if(X_N % 2 == 1):
        for n in range(X_N // 2):
          partName_1 = 'Part-' + str(y+1) + '-' + str(2*n+2) + '-1'
          partName_2 = 'Part-' + str(y+1) + '-' + str(2*n+3) + '-1'
          addHinge(partName_1, 2, partName_2, 3, count)
          count += 1

    # 偶数行
    if(y % 2 == 1):
      
      # 偶数行上方的转动副
      for j in range(X_N // 2):
        partName_1 = 'Part-' + str(y+1) + '-' + str(2*j+1) + '-1'
        partName_2 = 'Part-' + str(y+1) + '-' + str(2*j+2) + '-1'
        addHinge(partName_1, 2, partName_2, 3, count)
        count += 1
      
      # 偶数行，奇数列时，下方的转动副
      if(X_N % 2 == 0):
        for a in range(X_N // 2 - 1):
          partName_1 = 'Part-' + str(y+1) + '-' + str(2*a+2) + '-1'
          partName_2 = 'Part-' + str(y+1) + '-' + str(2*a+3) + '-1'
          addHinge(partName_1, 1, partName_2, 0, count)
          count += 1
      
      # 偶数行，偶数列时，下方的转动副
      if(X_N % 2 == 1):
        for b in range(X_N // 2):
          partName_1 = 'Part-' + str(y+1) + '-' + str(2*b+2) + '-1'
          partName_2 = 'Part-' + str(y+1) + '-' + str(2*b+3) + '-1'
          addHinge(partName_1, 1, partName_2, 0, count)
          count += 1
  
  # 第x列矩形之间的转动副
  for x in range(X_N):

    # 奇数列
    if(x % 2 == 0):
      
      # 奇数列右边的转动副
      for c in range(Y_N // 2):
        partName_1 = 'Part-' + str(2*c+1) + '-' + str(x+1) + '-1'
        partName_2 = 'Part-' + str(2*c+2) + '-' + str(x+1) + '-1'
        addHinge(partName_1, 2, partName_2, 1, count)
        count += 1
      
      # 奇数列，偶数行时，左边的转动副
      if(Y_N % 2 == 0):
        for d in range(Y_N // 2 - 1):
          partName_1 = 'Part-' + str(2*d+2) + '-' + str(x+1) + '-1'
          partName_2 = 'Part-' + str(2*d+3) + '-' + str(x+1) + '-1'
          addHinge(partName_1, 3, partName_2, 0, count)
          count += 1
      
      # 奇数列，奇数行时，左边的转动副
      if(Y_N % 2 == 1):
        for e in range(Y_N // 2):
          partName_1 = 'Part-' + str(2*e+2) + '-' + str(x+1) + '-1'
          partName_2 = 'Part-' + str(2*e+3) + '-' + str(x+1) + '-1'
          addHinge(partName_1, 3, partName_2, 0, count)
          count += 1

    # 偶数列
    if(x % 2 == 1):
      
      # 偶数列左边的转动副
      for f in range(Y_N // 2):
        partName_1 = 'Part-' + str(2*f+1) + '-' + str(x+1) + '-1'
        partName_2 = 'Part-' + str(2*f+2) + '-' + str(x+1) + '-1'
        addHinge(partName_1, 3, partName_2, 0, count)
        count += 1
      
      # 偶数列，奇数行时，右边的转动副
      if(Y_N % 2 == 0):
        for g in range(X_N // 2 - 1):
          partName_1 = 'Part-' + str(2*g+2) + '-' + str(x+1) + '-1'
          partName_2 = 'Part-' + str(2*g+3) + '-' + str(x+1) + '-1'
          addHinge(partName_1, 2, partName_2, 1, count)
          count += 1
      
      # 偶数列，偶数行时，右边的转动副
      if(Y_N % 2 == 1):
        for h in range(X_N // 2):
          partName_1 = 'Part-' + str(2*h+2) + '-' + str(x+1) + '-1'
          partName_2 = 'Part-' + str(2*h+3) + '-' + str(x+1) + '-1'
          addHinge(partName_1, 2, partName_2, 1, count)
          count += 1

  print('Hinge num: %d' % count)

# 设置材料属性
def setMaterial():
  mdb.models['Model-1'].Material(name='Material-1')
  mdb.models['Model-1'].materials['Material-1'].Elastic(table=((YOUNGS_MODULUS, POISSONS_RATIO), 
    ))
  mdb.models['Model-1'].HomogeneousShellSection(idealization=NO_IDEALIZATION, 
    integrationRule=SIMPSON, material='Material-1', name='Section-1', 
    numIntPts=5, poissonDefinition=DEFAULT, preIntegrate=OFF, temperature=
    GRADIENT, thickness=THICKNESS, thicknessField='', thicknessModulus=None, 
    thicknessType=UNIFORM, useDensity=OFF)

# 赋予各个part材料属性
def assignMaterial():
  for i in range(Y_N):
    for j in range(X_N):
      partName = "Part-" + str(i+1) + '-' + str(j+1)
      mdb.models['Model-1'].parts[partName].SectionAssignment(offset=0.0, 
        offsetField='', offsetType=MIDDLE_SURFACE, region=Region(
        faces=mdb.models['Model-1'].parts[partName].faces.getSequenceFromMask(
        mask=('[#1 ]', ), )), sectionName='Section-1', thicknessAssignment=
        FROM_SECTION)

# 为所有part划分网格
def mesh():
  for i in range(Y_N):
    for j in range(X_N):
      partName = "Part-" + str(i+1) + '-' + str(j+1)
      mdb.models['Model-1'].parts[partName].seedPart(deviationFactor=0.1, 
          minSizeFactor=0.1, size=1.0)
      mdb.models['Model-1'].parts[partName].generateMesh()

# 创建分析步，固定步长0.02，共50帧
def step():
  mdb.models['Model-1'].StaticStep(initialInc=0.02, name='Step-1', nlgeom=ON, 
    noStop=OFF, previous='Initial', timeIncrementationMethod=AUTOMATIC)

# 添加边界条件
def load():
  mdb.models['Model-1'].DisplacementBC(amplitude=UNSET, createStepName='Initial', 
    distributionType=UNIFORM, fieldName='', localCsys=None, name='BC-1', 
    region=Region(
    vertices=mdb.models['Model-1'].rootAssembly.instances['Part-1-1-1'].vertices.getSequenceFromMask(
    mask=('[#1 ]', ), )), u1=SET, u2=SET, u3=SET, ur1=SET, ur2=SET, ur3=UNSET)

  partName = 'Part-' + str(X_N) + '-' + str(Y_N) + '-1'
  mdb.models['Model-1'].ConcentratedForce(cf1=1000.0, cf2=1000.0, createStepName=
    'Step-1', distributionType=UNIFORM, field='', localCsys=None, name='Load-1'
    , region=Region(
    vertices=mdb.models['Model-1'].rootAssembly.instances[partName].vertices.getSequenceFromMask(
    mask=('[#4 ]', ), )))

def job():
  mdb.Job(atTime=None, contactPrint=OFF, description='', echoPrint=OFF, 
    explicitPrecision=SINGLE, getMemoryFromAnalysis=True, historyPrint=OFF, 
    memory=90, memoryUnits=PERCENTAGE, model='Model-1', modelPrint=OFF, 
    multiprocessingMode=DEFAULT, name='Job-1', nodalOutputPrecision=SINGLE, 
    numCpus=1, numGPUs=0, queue=None, resultsFormat=ODB, scratch='', type=
    ANALYSIS, userSubroutine='', waitHours=0, waitMinutes=0)

arrayPart()
assembly()
arrayHinge()
setMaterial()
assignMaterial()
mesh()
step()
load()
job()

print(" ")
# 打印参数
print("A: %s " % A)
print("B: %s " % B)
print("X_N: %d " % X_N)
print("Y_N: %d " % Y_N)
# Save by cgp on 2021_11_25-17.25.55; build 6.14-5 2015_08_18-22.37.49 135153
